package com.sh.rbac.core.encrypt.filter;

import com.sh.rbac.core.encrypt.annotation.ApiEncrypt;
import com.sh.rbac.core.encrypt.filter.wrapper.DecryptRequestBodyWrapper;
import com.sh.rbac.core.encrypt.filter.wrapper.EncryptResponseBodyWrapper;
import com.sh.rbac.core.encrypt.properties.ApiEncryptProperties;
import com.sh.rbac.core.encrypt.properties.EncryptProperties;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.io.IOException;

/**
 * 加密过滤器
 *
 * @author wb
 * @since 2025-10-20
 */

@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
@Component
public class EncryptFilter implements Filter {

    @Autowired
    private EncryptProperties encryptProperties;

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        ApiEncryptProperties apiEncrypt = encryptProperties.getApiEncrypt();

        boolean encryptEnable = getApiEncrypt(request) != null && apiEncrypt.isEnable();
        String headerFlag = apiEncrypt.getHeaderFlag();
        String encryptHeader = request.getHeader(headerFlag);

        // 处理请求解密
        if (encryptHeader != null) {
            request = new DecryptRequestBodyWrapper(request, encryptHeader, apiEncrypt.getPrivateKey());
        }

        // 处理响应加密
        if (encryptEnable) {
            EncryptResponseBodyWrapper encryptResponse = new EncryptResponseBodyWrapper(response);
            filterChain.doFilter(request, encryptResponse);

            String responseData = encryptResponse.getCaptureAsString();
            if (responseData != null && !responseData.isEmpty()) {
                response.reset();
                String encryptContent = encryptResponse.getEncryptContent(response, apiEncrypt.getPublicKey(), headerFlag);
                response.getWriter().write(encryptContent);
            }
        } else {
            filterChain.doFilter(request, response);
        }
    }


    private ApiEncrypt getApiEncrypt(HttpServletRequest request) {
        try {
            HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(request);
            if (chain != null) {
                Object handler = chain.getHandler();
                if (handler instanceof HandlerMethod m) {
                    return m.getMethodAnnotation(ApiEncrypt.class);
                }
            }
        } catch (Exception e) {
            log.info("获取方法注解失败", e);
        }

        return null;
    }
}
